﻿<GlobalAvalibleObjectImplementation(singleton:=True)>
Public Class ContentEditor

    Private content_type_map As New Dictionary(Of Type, IContentTypeEditor)
    Private generic As Type = GetType(ContentTypeEditor(Of ))


    Public Function editProperty(content As IContent, property_name As String, value As String) As Boolean
        If content Is Nothing Then Return False
        If String.IsNullOrEmpty(property_name) Then Return False
        Dim object_type As Type = content.GetType()
        If Not content_type_map.ContainsKey(object_type) Then
            Dim fa As FastActivator = getGlobalObject(Of FastActivator)()
            Dim this_type As Type = generic.MakeGenericType(object_type)
            content_type_map(object_type) = fa.createInstance(this_type)
        End If

        Return content_type_map(object_type).editProperty(content, property_name, value)

    End Function

    Private Interface IContentTypeEditor
        Function editProperty(content As IContent, property_name As String, value As String) As Boolean
    End Interface

    Private Class ContentTypeEditor(Of T As IContent)
        Implements IContentTypeEditor

        Private _content_type As ContentType
        Private _write_properties As New Dictionary(Of String, ContentProperty)
        Private _reference_properties As New Dictionary(Of String, ContentReference)

        Private _property_instancer As New Dictionary(Of String, IActivator)


        Sub New()
            _content_type = getMystery().AssemblyRegister.getMysteryClassAttribute(Of ContentType, T)()

            Dim all As IEnumerable(Of ContentProperty) = getMystery().AssemblyRegister.getMysteryPropertyAttributes(Of ContentProperty, T)()
            For Each cp As ContentProperty In all
                _write_properties(cp.name) = cp
            Next
            Dim references As IEnumerable(Of ContentReference) = getMystery.AssemblyRegister.getMysteryPropertyAttributes(Of ContentReference, T)()
            For Each cr As ContentReference In references
                _reference_properties(cr.name) = cr
            Next

            Dim fa As FastActivator = getGlobalObject(Of FastActivator)()

            For Each wp As ContentProperty In _write_properties.Values
                'fedding _property_instancer
                Dim pt As Type = wp.used_in.PropertyType.GetGenericArguments.FirstOrDefault
                _property_instancer(wp.name) = fa.getActivator(wp.used_in.PropertyType)
            Next

            For Each wp As ContentReference In _reference_properties.Values
                'fedding _property_instancer
                Dim target_type As Type = wp.used_in.PropertyType.GetGenericArguments.FirstOrDefault
                _property_instancer(wp.name) = fa.getActivator(wp.used_in.PropertyType)
            Next

        End Sub


        Public Function editProperty(content As IContent, property_name As String, value As String) As Boolean Implements IContentTypeEditor.editProperty
            If content Is Nothing Then Return False
            If String.IsNullOrEmpty(property_name) Then Return False
            If Not _property_instancer.ContainsKey(property_name) Then Return False

            'reference or normal?
            If _write_properties.ContainsKey(property_name) Then
                Dim pv As ContentPropertyValue = _property_instancer(property_name).createInstance
                pv.setValue(value)
                _write_properties(property_name).save()(content, pv)
            ElseIf _reference_properties.ContainsKey(property_name) Then
                Dim pv As BaseContentReference = _reference_properties(property_name).retrive()(content)
                If value Is Nothing Then value = String.Empty
                pv.setWithGuids(From x As String In value.Split(",") Select Guid.Parse(x.Trim()))
            Else
                'wth?
                Return False
            End If

            Return True
        End Function

    End Class


End Class



